home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / launchpad-integration / launchpadintegration / packageinfo.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-10-28  |  11KB  |  307 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''
  5. Code used to identify a package based on one of the following:
  6.  * A process ID
  7.  * A file name
  8.  * A desktop file
  9.  * A binary package name
  10. '''
  11. import sys
  12. import os
  13. import socket
  14. import subprocess
  15. DPKGDIR = '/var/lib/dpkg'
  16. INFODIR = os.path.join(DPKGDIR, 'info')
  17. STATUSFILE = os.path.join(DPKGDIR, 'status')
  18.  
  19. class PackageNotFoundError(Exception):
  20.     pass
  21.  
  22.  
  23. def _get_pkg(filename):
  24.     """Find the binary package associated with the given filename
  25.  
  26.     This scans the list files in /var/lib/dpkg/info, since it is faster
  27.     than 'dpkg-query -S'.
  28.     """
  29.     for listfile in os.listdir(INFODIR):
  30.         if not listfile.endswith('.list'):
  31.             continue
  32.         
  33.         contents = open(os.path.join(INFODIR, listfile), 'r').read()
  34.         if filename in contents.splitlines(False):
  35.             return listfile[:-len('.list')]
  36.     
  37.  
  38.  
  39. class PackageInfo(object):
  40.     
  41.     def __init__(self, binarypackage, sourcepackage, provides, version, architecture, status, dependencies):
  42.         self.binarypackage = binarypackage
  43.         if not sourcepackage:
  44.             pass
  45.         self.sourcepackage = binarypackage
  46.         self.provides = set(provides)
  47.         self.version = version
  48.         self.architecture = architecture
  49.         self.status = status
  50.         self.dependencies = set(dependencies)
  51.         self.names = set(self.provides)
  52.         self.names.add(self.binarypackage)
  53.  
  54.     
  55.     def installed(self):
  56.         if self.status:
  57.             state = self.status.split()[2]
  58.             return state not in ('config-files', 'not-installed')
  59.         return False
  60.  
  61.     installed = property(installed)
  62.     
  63.     def shortstatus(self):
  64.         if self.status:
  65.             sinfo = self.status.split()
  66.             return sinfo[0][0] + sinfo[2][0]
  67.         return None
  68.  
  69.     shortstatus = property(shortstatus)
  70.     
  71.     def __repr__(self):
  72.         return "<PackageInfo '%s_%s_%s'>" % (self.binarypackage, self.version, self.architecture)
  73.  
  74.     
  75.     def fromXID(cls, xid = None, logger = None):
  76.         """Return a PackageInfo instance corresponding to a window
  77.  
  78.         This is performed by calling xprop to get WM_CLIENT_MACHINE
  79.         and _NET_WM_PID properties of a window.  If WM_CLIENT_MACHINE
  80.         is our hostname, and _NET_WM_PID is set, then chain to
  81.         fromProcessID().
  82.  
  83.         If no XID is passed, xprop works in 'picker' mode.
  84.         """
  85.         cmdline = [
  86.             'xprop',
  87.             '-notype']
  88.         if xid is not None:
  89.             cmdline.extend([
  90.                 '-id',
  91.                 str(xid)])
  92.         
  93.         cmdline.extend([
  94.             'WM_CLIENT_MACHINE',
  95.             '_NET_WM_PID'])
  96.         if logger:
  97.             logger.debug('Executing %r', cmdline)
  98.         
  99.         
  100.         try:
  101.             p = subprocess.Popen(cmdline, stdout = subprocess.PIPE, stderr = subprocess.PIPE, close_fds = True)
  102.             (stdout, stderr) = p.communicate()
  103.             result = p.returncode
  104.         except (OSError, IOError):
  105.             if logger:
  106.                 logger.exception('Could not find process ID')
  107.             
  108.             raise PackageNotFoundError('Could not find process ID')
  109.  
  110.         if result != 0:
  111.             raise PackageNotFoundError('Could not find process ID')
  112.         result != 0
  113.         props = dict((lambda .0: for x in .0:
  114. x.split(' = ', 1))(stdout.splitlines(False)))
  115.         if logger:
  116.             logger.debug('WM_CLIENT_MACHINE = %s, _NET_WM_PID = %s', props.get('WM_CLIENT_MACHINE'), props.get('_NET_WM_PID'))
  117.         
  118.         hostname = '"%s"' % socket.gethostname()
  119.         if props.get('WM_CLIENT_MACHINE', hostname) != hostname or '_NET_WM_PID' not in props:
  120.             raise PackageNotFoundError('Could not find process ID')
  121.         '_NET_WM_PID' not in props
  122.         
  123.         try:
  124.             pid = int(props['_NET_WM_PID'])
  125.         except ValueError:
  126.             raise PackageNotFoundError('Could not find process ID')
  127.  
  128.         if logger:
  129.             logger.info('Process ID for selected window is %d', pid)
  130.         
  131.         return cls.fromProcessID(pid, logger)
  132.  
  133.     fromXID = classmethod(fromXID)
  134.     
  135.     def fromProcessID(cls, pid, logger = None):
  136.         '''Return a PackageInfo instance corresponding to a process ID
  137.  
  138.         This is performed by looking up the executable name in the /proc
  139.         filesystem, then chaining to fromFilename().
  140.         '''
  141.         if logger:
  142.             logger.debug('Looking up executable for process %d', pid)
  143.         
  144.         
  145.         try:
  146.             filename = os.readlink('/proc/%d/exe' % pid)
  147.         except OSError:
  148.             if logger:
  149.                 logger.exception('Could not find executable for process %d', pid)
  150.             
  151.             raise PackageNotFoundError('Could not find executable for process %d' % pid)
  152.  
  153.         if filename.endswith(' (deleted)'):
  154.             logger.error('Process %d is running deleted executable "%s"', pid, filename)
  155.             raise PackageNotFoundError('Process %d is running deleted executable "%s"' % (pid, filename))
  156.         filename.endswith(' (deleted)')
  157.         if logger:
  158.             logger.info('Executable for process %d is "%s"', pid, filename)
  159.         
  160.         if filename.startswith('/rofs'):
  161.             filename = filename[len('/rofs'):]
  162.         elif filename.startswith('/filesystem.squashfs'):
  163.             filename = filename[len('/filesystem.squashfs'):]
  164.         
  165.         return cls.fromFilename(filename, logger)
  166.  
  167.     fromProcessID = classmethod(fromProcessID)
  168.     
  169.     def fromDesktopFile(cls, filename, logger = None):
  170.         """Return a PackageInfo instance corresponding to a Desktop file
  171.  
  172.         This is performed by looking for the executable name in the 'exec'
  173.         line of the desktop file, then chains to fromFilename().
  174.  
  175.         This function should be used instead of fromFilename() because
  176.         the desktop file might be a customised one in the user's home
  177.         directory, but still points to an installed application.
  178.         """
  179.         raise NotImplementedError
  180.  
  181.     fromDesktopFile = classmethod(fromDesktopFile)
  182.     
  183.     def fromFilename(cls, filename, logger = None):
  184.         '''Return a PackageInfo instance corresponding to a file
  185.  
  186.         This is performed by finding the package that owns the file
  187.         using dpkg-query, and then chaining to fromPackageName to
  188.         fill in the PackageInfo instance.
  189.         '''
  190.         if logger:
  191.             logger.debug('Looking up binary package name for file "%s"', filename)
  192.         
  193.         
  194.         try:
  195.             package = _get_pkg(filename)
  196.         except (OSError, IOError):
  197.             if logger:
  198.                 logger.exception('Could not find binary package for file "%s"', filename)
  199.             
  200.             raise PackageNotFoundError('Could not find binary package for file "%s"' % filename)
  201.  
  202.         if package is None:
  203.             raise PackageNotFoundError('Could not look up binary package for file "%s"' % filename)
  204.         package is None
  205.         if logger:
  206.             logger.info('Binary package for file "%s" is "%s"', filename, package)
  207.         
  208.         return cls.fromPackageName(package, logger)
  209.  
  210.     fromFilename = classmethod(fromFilename)
  211.     
  212.     def fromPackageName(cls, package, logger = None):
  213.         '''Return a PackageInfo instance for a particular binary package name
  214.         '''
  215.         if logger:
  216.             logger.debug('Looking up package information for "%s"', package)
  217.         
  218.         for info in cls._iterPackages():
  219.             if package in info.names:
  220.                 break
  221.                 continue
  222.         else:
  223.             raise PackageNotFoundError('Could not look up package info for "%s"' % package)
  224.         if None:
  225.             logger.debug('Package info for %s is %r', package, info)
  226.         
  227.         return info
  228.  
  229.     fromPackageName = classmethod(fromPackageName)
  230.     
  231.     def fromPackageNames(cls, packages, logger = None):
  232.         '''Iterate through PackageInfo instances that match names in packages.
  233.  
  234.         This is an optimisation of fromPackageName() for when you want
  235.         multiple packages.
  236.         '''
  237.         packages = set(packages)
  238.         for info in cls._iterPackages():
  239.             if packages & info.names:
  240.                 if logger:
  241.                     logger.debug('Package %r matched', info)
  242.                 
  243.                 yield info
  244.                 continue
  245.         
  246.  
  247.     fromPackageNames = classmethod(fromPackageNames)
  248.     
  249.     def _iterPackages(cls, filename = STATUSFILE):
  250.         '''Iterate through the list of packages in the DPKG database'''
  251.         package = None
  252.         status = None
  253.         architecture = None
  254.         source = None
  255.         version = None
  256.         provides = []
  257.         dependencies = []
  258.         for line in open(filename, 'r'):
  259.             if line == '\n':
  260.                 yield cls(binarypackage = package, sourcepackage = source, provides = provides, version = version, architecture = architecture, status = status, dependencies = dependencies)
  261.                 package = None
  262.                 status = None
  263.                 architecture = None
  264.                 source = None
  265.                 version = None
  266.                 provides = []
  267.                 dependencies = []
  268.                 continue
  269.             if line.startswith('Package: '):
  270.                 package = line[len('Package: '):].strip()
  271.                 continue
  272.             if line.startswith('Status: '):
  273.                 status = line[len('Status: '):].strip()
  274.                 continue
  275.             if line.startswith('Architecture: '):
  276.                 architecture = line[len('Architecture: '):].strip()
  277.                 continue
  278.             if line.startswith('Source: '):
  279.                 source = line[len('Source: '):].strip()
  280.                 continue
  281.             if line.startswith('Version: '):
  282.                 version = line[len('Version: '):].strip()
  283.                 continue
  284.             if line.startswith('Provides: '):
  285.                 provides.extend((lambda .0: for x in .0:
  286. x.strip())(line[len('Provides: '):].split(', ')))
  287.                 continue
  288.             if line.startswith('Depends: '):
  289.                 deps = line[len('Depends: '):].strip()
  290.                 dependencies.extend((lambda .0: for x in .0:
  291. for y in x.split('|'):
  292. y.split()[0])(deps.split(', ')))
  293.                 continue
  294.             if line.startswith('Pre-Depends'):
  295.                 deps = line[len('Pre-Depends: '):].strip()
  296.                 dependencies.extend((lambda .0: for x in .0:
  297. for y in x.split('|'):
  298. y.split()[0])(deps.split(', ')))
  299.                 continue
  300.         
  301.         if package is not None:
  302.             yield cls(binarypackage = package, sourcepackage = source, provides = provides, version = version, architecture = architecture, status = status, dependencies = dependencies)
  303.         
  304.  
  305.     _iterPackages = classmethod(_iterPackages)
  306.  
  307.